import java.io.PrintStream;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestProcessor {

    private PrintStream origOutStream, origErrStream, fileStream;
    private final String logFilename = "log.txt";

    public void redirectOutput() {
        try {
            origOutStream = System.out;
            origErrStream = System.err;
            // ensure log file is empty
            Out out = new Out(logFilename);
            out.close();
            fileStream = new PrintStream(new FileOutputStream(logFilename, true));
            // redirect output
            System.setOut(fileStream);
            System.setErr(fileStream);
        } catch (FileNotFoundException e) {
            StdOut.println("Redirect error");
        }
    }

    public void restoreOutput() {
        System.setOut(origOutStream);
        System.setErr(origErrStream);
    }

    public void runFileTest(String processor, String inputfile, String expectedoutput) throws ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
        System.out.format("Testing %s with file %s...", processor, inputfile);
        // Invoke main(0) method of class named by the first argument
        Class<?> c = Class.forName(processor);
        Object t = c.newInstance();
        assert t!=null : "Unable to create instance of " + processor;
        Method[] allMethods = c.getDeclaredMethods();
        boolean invoked = false;
        for (Method m : allMethods) {
            if (m.getName() == "main") {
                m.setAccessible(true);
                redirectOutput();
                try {
                    m.invoke(t, (Object)new String[] { inputfile });
                } finally {
                    restoreOutput();
                }
                invoked = true;
                break;
            }
        }
        assert invoked : "Unable to invoke main() method of " + processor;


        // check the output
        In in = new In(logFilename);
        String resultString = in.readAll();
        assert expectedoutput.equals(resultString) : "Expected output \"" + expectedoutput + "\"but instead got \"" + resultString + "\"";
        System.out.format("passed\n");
    }

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
        TestProcessor tp = new TestProcessor();
        tp.runFileTest("Brute", "./input6.txt", "(14000, 10000) -> (18000, 10000) -> (19000, 10000) -> (21000, 10000) -> (32000, 10000)\n");
        tp.runFileTest("Fast", "./input6.txt", "(14000, 10000) -> (18000, 10000) -> (19000, 10000) -> (21000, 10000) -> (32000, 10000)\n");
    }
}